/**
 * 
 */
package boundary.components;

import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionAdapter;
import java.io.File;

import javax.swing.ButtonGroup;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.SwingConstants;
import javax.swing.event.MenuEvent;
import javax.swing.event.MenuListener;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;

import calculator.CoordinateManager;
import calculator.FileUtils;
import calculator.MenuBuilder;

import executor.QuadTree;

import boundary.ChildWindow;
import boundary.MainWindow;

/**
 * @author davide
 *
 */
public class MyJLabel extends JLabel
{
    private static final long serialVersionUID = 958695572873969749L;
    
    public enum InsertingState {
	INSERTING_NOTHING,
	INSERTING_UPPERVX,
	INSERTING_LOWERVX,
	INSERTING_WAITING,
	INSERTING_POLYGON
    }
    
    File file;			/** physical file */
    int zoomFactor;		/** current zoom factor */
    ImageIcon content;		/** displayed image */
    Dimension contentSize;	/** original image size */
    SmartPolygon polygon;	/** polygon area */
    ActiveImage activeImage;	/** active image area */
    QuadTree quadTree;		/** quad tree associated to the image */
    Color internalColor;	/** gap used inside polygon */
    Color externalColor;	/** gap used outside polygon */
    
    ChildWindow parent;		/** component container */
    InsertingState insertingState = InsertingState.INSERTING_NOTHING;
    

    public MyJLabel(File f, ChildWindow ancestor) throws IllegalArgumentException
    {
	super();
	
	this.file = f;
	this.parent = ancestor;
	
	this.quadTree = null;
	this.activeImage = new ActiveImage();
	this.polygon = new SmartPolygon();
	
	this.internalColor = new Color(Color.black.getRGB());
	this.externalColor = new Color(Color.black.getRGB());
	
	this.setViewableImage(this.file.getAbsolutePath());
	this.setProperties();
    }
    
    public MyJLabel(File f, QuadTree qtree, ChildWindow ancestor) throws IllegalArgumentException
    {
	super();
	
	this.file = f;
	this.parent = ancestor;
	
	this.quadTree = qtree;
	this.activeImage = new ActiveImage();
	this.polygon = new SmartPolygon();
	
	this.internalColor = new Color(Color.black.getRGB());
	this.externalColor = new Color(Color.black.getRGB());
	
	this.setViewableImage(qtree);
	this.setProperties();
    }
    
    public MyJLabel(File f, Image image, ChildWindow ancestor) throws IllegalArgumentException
    {
	super();
	
	this.file = f;
	this.parent = ancestor;
	
	this.quadTree = null;
	this.activeImage = new ActiveImage();
	this.polygon = new SmartPolygon();
	
	this.internalColor = new Color(Color.black.getRGB());
	this.externalColor = new Color(Color.black.getRGB());
	
	this.setViewableImage(image);
	this.setProperties();
    }
    
    public File getFile()
    {
        return this.file;
    }

    public ImageIcon getContent()
    {
        return this.content;
    }
    
    public void setContent(ImageIcon image)
    {
        this.content = image;
    }
    
    public Dimension getContentSize()
    {
        return this.contentSize;
    }

    public void setContentSize(Dimension cSize)
    {
        this.contentSize = cSize;
    }

    public int getZoomFactor()
    {
        return this.zoomFactor;
    }

    public void setZoomFactor(int zFactor)
    {
        this.zoomFactor = zFactor;
    }

    public ActiveImage getActiveImage()
    {
        return this.activeImage;
    }

    public SmartPolygon getPolygon()
    {
        return this.polygon;
    }

    public QuadTree getQuadTree()
    {
        return this.quadTree;
    }
    
    public void setQuadTree(QuadTree qTree)
    {
        this.quadTree = qTree;
    }

    public Color getInternalColor()
    {
        return this.internalColor;
    }

    public void setInternalColor(Color iColor)
    {
        this.internalColor = iColor;
    }

    public Color getExternalColor()
    {
        return this.externalColor;
    }

    public void setExternalColor(Color eColor)
    {
        this.externalColor = eColor;
    }
    
    public InsertingState getInsertingState()
    {
        return this.insertingState;
    }

    public void beginInsertingState(InsertingState nextState)
    {
	this.insertingState = nextState;
	this.setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR));
    }
    
    public void endInsertingState(InsertingState nextState)
    {
	switch(this.insertingState)
	{
		case INSERTING_NOTHING :
		case INSERTING_WAITING :
		case INSERTING_LOWERVX : {
		    if(nextState == InsertingState.INSERTING_WAITING) {
			this.quadTree = QuadTree.read(this.activeImage.x,
        	    		this.activeImage.y, this.activeImage.width,
        	    		this.content.getImage());
		    }
		    
		    break;
		}
		
		default : {
		    break;
		}
	}
	
	this.insertingState = nextState;
	this.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
    }
    
    private void setViewableImage(String filePath) throws IllegalArgumentException
    {
	try {
	    this.content = new ImageIcon(filePath);
	
	    if(this.content.getImageLoadStatus() != MediaTracker.COMPLETE) {
		throw new Exception();
	    }
	}
	
	catch(Exception ex) {
	    throw new IllegalArgumentException(
		    "Il file specificato non sembra essere un'immagine valida");
	}
    }
    
    private void setViewableImage(Image image) throws IllegalArgumentException
    {
	try {
	    this.content = new ImageIcon(image);
	
	    if(this.content.getImageLoadStatus() != MediaTracker.COMPLETE) {
		throw new Exception();
	    }
	}
	
	catch(Exception ex) {
	    throw new IllegalArgumentException(
		    "L'immagine generata non sembra essere un'immagine valida");
	}
    }
    
    private void setViewableImage(QuadTree qtree) throws IllegalArgumentException
    {
	try {
	    this.quadTree = qtree;
	    
	    this.quadTree.prepareImage(new Color(Color.black.getRGB()));
	    
	    this.content = new ImageIcon(this.quadTree.getImage());
	    
	    if(this.content.getImageLoadStatus() != MediaTracker.COMPLETE) {
		    throw new Exception();
	    }
	}
	
	catch(Exception ex) {
	    throw new IllegalArgumentException(
		    "Il file specificato non sembra essere un QuadTree valido");
	}
    }

    private void setProperties()
    {	
	this.contentSize = new Dimension(this.content.getIconWidth(), this.content.getIconHeight());
	
	this.setHorizontalAlignment(SwingConstants.LEFT);
	this.setVerticalAlignment(SwingConstants.TOP);
	
	this.addMouseListener(this.addPopUpMenu());
	
	this.addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e)
            {
        	if(e.getButton() == MouseEvent.BUTTON1)
        	{
        	    switch(MyJLabel.this.insertingState)
        	    {
        	    	case INSERTING_UPPERVX :
        	    	{
        	    	    // be sure to be inside displayed image
        	    	    if(e.getX() < MyJLabel.this.contentSize.width &&  e.getY() < MyJLabel.this.contentSize.height)
        	    	    {
        	    		MyJLabel.this.activeImage.setLocation(e.getX(), e.getY(), MyJLabel.this.zoomFactor);
        	    		MyJLabel.this.insertingState = InsertingState.INSERTING_LOWERVX;
        	    		
        	    		MyJLabel.this.repaint();
        	    	    }
        	    	    
        	    	    break;
        	    	}
        	    	
        	    	case INSERTING_LOWERVX :
        	    	{
        	    	    // be sure to be inside displayed image
        	    	    if(e.getX() < MyJLabel.this.contentSize.width &&  e.getY() < MyJLabel.this.contentSize.height)
        	    	    {
        	    		MyJLabel.this.activeImage.setLowerBoundAndClose(e.getX(), e.getY(), MyJLabel.this.zoomFactor);
        	    		MyJLabel.this.endInsertingState(InsertingState.INSERTING_WAITING);
        	    		
        	    		MyJLabel.this.repaint();
        	    	    }
        	    	    
        	    	    break;
        	    	}
        	    	
        	    	case INSERTING_POLYGON :
        	    	{
        	    	    // be sure to be inside active image
        	    	    if(MyJLabel.this.activeImage.contains(e.getX(), e.getY(), MyJLabel.this.zoomFactor) == true)
        	    	    {
        	    		if(MyJLabel.this.polygon.addPoint(e.getX(), e.getY(), MyJLabel.this.zoomFactor) == true) {
        	    		    MyJLabel.this.endInsertingState(InsertingState.INSERTING_WAITING);
        	    		    
        	    		    // real time update of compressing
        	    		    if(MyJLabel.this.parent.getCompress().isVisible() ||
        	    			    !MyJLabel.this.getInternalColor().equals(Color.black) ||
        	    			!MyJLabel.this.getExternalColor().equals(Color.black))
        	    		    {
        	    			MyJLabel.this.parent.getCompress().updateImage();
        	    		    }
        	    		}
        		
        	    		MyJLabel.this.repaint();
        	    	    }
        	    	    
        	    	    break;
        	    	}
        	    	
        	    	default : {
        	    	    break;
        	    	}
        	    }
        	}
        	
        	MainWindow.menuShortcutsBugWorkaround();
            }
	});
	
	this.addMouseMotionListener(new MouseMotionAdapter() {
            @Override
            public void mouseMoved(MouseEvent e)
            {
        	switch(MyJLabel.this.insertingState)
        	{
        		case INSERTING_LOWERVX :
        		{
        		    // be sure to be inside displayed image
        		    if(e.getX() < MyJLabel.this.contentSize.width &&  e.getY() < MyJLabel.this.contentSize.height)
        		    {
        			MyJLabel.this.activeImage.setLowerBound(e.getX(), e.getY(), MyJLabel.this.zoomFactor);
        		    }
        		    
        		    else {
        			MyJLabel.this.activeImage.reset();
        		    }
        		    
        		    MyJLabel.this.repaint();
        		    break;
        		}
	    	
        		case INSERTING_POLYGON :
        		{
        		    // be sure to be inside active image
        	    	    if(MyJLabel.this.activeImage.contains(e.getX(), e.getY(), MyJLabel.this.zoomFactor) == true)
        		    {
        			if(MyJLabel.this.polygon.isClosing(e.getX(), e.getY(), MyJLabel.this.zoomFactor)) {
        			    MyJLabel.this.setCursor(new Cursor(Cursor.HAND_CURSOR));
        			}
        		
        			else {
        			    MyJLabel.this.setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR));
        			}
        		
        			MyJLabel.this.polygon.setCursorLocation(e.getX(), e.getY(), MyJLabel.this.zoomFactor);
        		    }
        	
        		    else {
        			MyJLabel.this.polygon.resetCursorLocation();
        		    }
        	
        		    MyJLabel.this.repaint();
        		    break;
        		}
        		
        		default : {
        		    break;
        		}
        	}
        	
        	MainWindow.menuShortcutsBugWorkaround();
            }
	});
	
	this.scaleImageContent(-1);
    }
    
    public void traslateAllGraphics(int dx, int dy)
    {
	this.activeImage.translate(dx, dy);
	this.polygon.translate(dx, dy);
	
	this.repaint();
    }
    
    public void scaleImageContent(int factor)
    {
	if(factor < 0) {
	    this.contentSize = this.scaleImageToFitWindow();
	}
	
	else {
	    this.contentSize = this.scaleImageToFixedFactor(factor);
	}
	
	this.setIcon(new ImageIcon(this.content.getImage().getScaledInstance(
		this.contentSize.width, this.contentSize.height, Image.SCALE_SMOOTH))
	);
	
	this.parent.setTitle(this.file.getName() + " - " +
		this.contentSize.width + "x" + this.contentSize.height +
		" (" + this.zoomFactor + "%)");
	
	this.tweakWindowSize();
	this.repaint();
    }
    
    public void cancelInsertion()
    {
	switch(this.insertingState)
	{
		case INSERTING_UPPERVX :
		case INSERTING_LOWERVX :
		{
		    this.polygon.reset();
		    this.activeImage.reset();
		    this.endInsertingState(InsertingState.INSERTING_NOTHING);
		    
		    break;
		}
	
		case INSERTING_POLYGON :
		{
		    this.polygon.reset();
		    this.endInsertingState(InsertingState.INSERTING_WAITING);
		    
		    break;
		}
		
		default : {
		    break;
		}
	}
	
	this.repaint();
	MainWindow.menuShortcutsBugWorkaround();
    }
    
    private void tweakWindowSize()
    {
	Dimension frameMaxSize = this.parent.getInternalFrameMaximumArea();
	
	if(this.contentSize.width < frameMaxSize.width &&
		this.contentSize.height < frameMaxSize.height) {
	    this.parent.pack();
	}
	
	else {
	    if(this.contentSize.width < frameMaxSize.width) {
		this.parent.setSize(this.contentSize.width, this.parent.getHeight());
	    }
	    
	    else {
		this.parent.setSize(frameMaxSize.width, this.parent.getHeight());
	    }
	    
	    if(this.contentSize.height < frameMaxSize.height) {
		this.parent.setSize(this.parent.getWidth(), this.contentSize.height);
	    }
	    
	    else {
		this.parent.setSize(this.parent.getWidth(), frameMaxSize.height);
	    }
	}
    }
    
    private Dimension scaleImageToFixedFactor(int factor)
    {
	this.zoomFactor = factor;
	
	this.contentSize.setSize(
		CoordinateManager.relativeCoord(this.content.getIconWidth(), this.zoomFactor),
		CoordinateManager.relativeCoord(this.content.getIconHeight(), this.zoomFactor));
	
	return this.contentSize;
    }
    
    private Dimension scaleImageToFitWindow()
    {
	Dimension frameSize = this.parent.getInternalFrameMaximumArea();
	
	this.zoomFactor = 100;
	this.contentSize.setSize(this.content.getIconWidth(), this.content.getIconHeight());
	
	while(this.contentSize.height > frameSize.height || this.contentSize.width > frameSize.width)
	{
	    this.contentSize = this.scaleImageToFixedFactor(this.zoomFactor - 10);
	}
	
	return this.contentSize;
    }
    
    // Some function ho haldle pop up menu
    private MouseListener addPopUpMenu()
    {
	JPopupMenu popup = new JPopupMenu();
	final JMenu polygonMenu = this.createPolygonMenu();
	final JMenu activeMenu = this.createActiveImageMenu();
	final JMenu generateMenu = this.createGenerateImageMenu();
	
	final JMenuItem outside = MenuBuilder.createMenuSubEntry(
		"Esporta",
		new ActionListener() {
		    @Override
		    public void actionPerformed(@SuppressWarnings("unused") ActionEvent arg0)
		    {
			MyJLabel.this.parent.saveQuadTreeImage();
		    }
		});
	
	final JMenuItem close = MenuBuilder.createMenuSubEntry("Chiudi",
		new ActionListener()
		{    
		    @Override
		    public void actionPerformed(@SuppressWarnings("unused") ActionEvent e)
		    {
			MainWindow.closeActiveWindow(MyJLabel.this.parent);
		    }
		});
	
	final JMenuItem compress = MenuBuilder.createMenuSubEntry("Comprimi",
		new ActionListener() {
	    		@Override
	    		public void actionPerformed(@SuppressWarnings("unused") ActionEvent e)
	    		{
	    		    MyJLabel.this.parent.createQuadTreeImageWindow();
	    		}
		});
	
	popup.add(activeMenu);
	popup.add(polygonMenu);
	popup.add(generateMenu);
	popup.add(this.createZoomMenu());
	popup.addSeparator();
	
	popup.add(compress);
	popup.add(outside);
	popup.add(close);
	
	popup.addPopupMenuListener(new PopupMenuListener() {
	    @Override
	    public void popupMenuWillBecomeVisible(@SuppressWarnings("unused") PopupMenuEvent e)
	    {		
		switch(MyJLabel.this.insertingState)
		{
			case INSERTING_NOTHING : {
			    activeMenu.setEnabled(true);
			    polygonMenu.setEnabled(false);
			    generateMenu.setEnabled(false);
			    outside.setEnabled(false);
			    compress.setEnabled(false);
			    break;
			}
			
			case INSERTING_UPPERVX :
			case INSERTING_LOWERVX :
			case INSERTING_POLYGON :
			{
			    activeMenu.setEnabled(false);
			    polygonMenu.setEnabled(false);
			    generateMenu.setEnabled(false);
			    outside.setEnabled(false);
			    compress.setEnabled(false);
			    break;
			}
			
			case INSERTING_WAITING :
			{
			    if(MyJLabel.this.getQuadTree() != null &&
				    MyJLabel.this.parent.getCompress().isVisible() == false)
			    {
				outside.setEnabled(true);
				activeMenu.setEnabled(true);
				compress.setEnabled(true);
			    }
			    
			    else {
				outside.setEnabled(false);
				activeMenu.setEnabled(false);
				compress.setEnabled(false);
			    }
			    
			    polygonMenu.setEnabled(true);
			    generateMenu.setEnabled(true);
			    break;
			}
		}
	    }
	    
	    @Override
	    public void popupMenuWillBecomeInvisible(@SuppressWarnings("unused") PopupMenuEvent e) {
		// unimplemented
	    }
	    
	    @Override
	    public void popupMenuCanceled(@SuppressWarnings("unused") PopupMenuEvent e) {
		// unimplemented
	    }
	});
	
	return new PopupListener(popup);
    }
    
    private JMenu createActiveImageMenu()
    {
	JMenu active = MenuBuilder.createMenuEntry("Area attiva");
	final JMenuItem draw, erase, maximizeTop, maximizeBottom, maximizeCenter;
	
	draw = MenuBuilder.createMenuSubEntry("Seleziona",
		new ImageIcon(FileUtils.getResource("active.png")),
		new ActionListener() {
                    @Override
		    public void actionPerformed(@SuppressWarnings("unused") ActionEvent e)
		    {
                	MyJLabel.this.parent.drawActiveImage();
		    }
		});
	
	erase = MenuBuilder.createMenuSubEntry("Cancella",
		new ImageIcon(FileUtils.getResource("eraser.png")),
		new ActionListener() {
                    @Override
		    public void actionPerformed(@SuppressWarnings("unused") ActionEvent e)
		    {
                	MyJLabel.this.parent.eraseActiveImage();
		    }
		});
	
	maximizeTop = MenuBuilder.createMenuSubEntry("Massima superiore",
		new ActionListener() {
                    @Override
		    public void actionPerformed(@SuppressWarnings("unused") ActionEvent e)
		    {
                	MyJLabel.this.parent.maximizedTopActiveImage();
		    }
		});
	
	maximizeBottom = MenuBuilder.createMenuSubEntry("Massima inferiore",
		new ActionListener() {
                    @Override
		    public void actionPerformed(@SuppressWarnings("unused") ActionEvent e)
		    {
                	MyJLabel.this.parent.maximizedBottomActiveImage();
		    }
		});
	
	maximizeCenter = MenuBuilder.createMenuSubEntry("Massima centrale",
		new ActionListener() {
                    @Override
		    public void actionPerformed(@SuppressWarnings("unused") ActionEvent e)
		    {
                	MyJLabel.this.parent.maximizedCenterActiveImage();
		    }
		});
	
	active.add(draw);
	active.add(maximizeTop);
	active.add(maximizeCenter);
	active.add(maximizeBottom);
	active.add(erase);
	
	active.addMenuListener(new MenuListener() {
	    @Override
	    public void menuSelected(@SuppressWarnings("unused") MenuEvent e)
	    {
		switch(MyJLabel.this.insertingState)
		{
			case INSERTING_NOTHING : {
			    draw.setEnabled(true);
			    maximizeTop.setEnabled(true);
			    maximizeBottom.setEnabled(true);
			    maximizeCenter.setEnabled(true);
			    erase.setEnabled(false);
			    break;
			}
			
			case INSERTING_WAITING :
			{
			    draw.setEnabled(false);
			    maximizeTop.setEnabled(false);
			    maximizeBottom.setEnabled(false);
			    maximizeCenter.setEnabled(false);
			    
			    if(MyJLabel.this.parent.getCompress().isVisible() ||
				    MyJLabel.this.parent.getCompress().isThisImageAlreadyCompressed) {
				erase.setEnabled(false);
			    }
			    
			    else {
				erase.setEnabled(true);
			    }
			    
			    break;
			}
				
			default : {
			    draw.setEnabled(false);
			    maximizeTop.setEnabled(false);
			    maximizeBottom.setEnabled(false);
			    maximizeCenter.setEnabled(false);
			    erase.setEnabled(false);
			    break;
			}
		}
	    }
	    
	    @Override
	    public void menuDeselected(@SuppressWarnings("unused") MenuEvent e) {
		// unimplemented
	    }
	    
	    @Override
	    public void menuCanceled(@SuppressWarnings("unused") MenuEvent e) {
		// unimplemented
	    }
	});
	
	return active;
    }
    
    private JMenu createPolygonMenu()
    {
	JMenu plg = MenuBuilder.createMenuEntry("Poligono", KeyEvent.VK_P);
	final JMenuItem create, erase;
	
	create = MenuBuilder.createMenuSubEntry("Crea",
		new ImageIcon(FileUtils.getResource("polygon.gif")),
		new ActionListener() {
                    @Override
		    public void actionPerformed(@SuppressWarnings("unused") ActionEvent e)
		    {
                	MyJLabel.this.parent.drawPolygon();
		    }
		});
	
	erase = MenuBuilder.createMenuSubEntry("Cancella",
		new ImageIcon(FileUtils.getResource("eraser.png")),
		new ActionListener() {
		    @Override
		    public void actionPerformed(@SuppressWarnings("unused") ActionEvent e)
		    {
			MyJLabel.this.parent.erasePolygon();
		    }
		});
	
	plg.add(create);
	plg.add(erase);
	
	plg.addMenuListener(new MenuListener() {
	    @Override
	    public void menuSelected(@SuppressWarnings("unused") MenuEvent e)
	    {
		switch(MyJLabel.this.insertingState)
		{
			case INSERTING_WAITING :
			{
			    if(MyJLabel.this.polygon.npoints == 0) {
				create.setEnabled(true);
				erase.setEnabled(false);
			    }
			    
			    else {
				create.setEnabled(false);
				erase.setEnabled(true);
			    }
			    
			    break;
			}
				
			default : {
			    erase.setEnabled(false);
			    create.setEnabled(false);
			    break;
			}
		}
	    }
	    
	    @Override
	    public void menuDeselected(@SuppressWarnings("unused") MenuEvent e) {
		// unimplemented
	    }
	    
	    @Override
	    public void menuCanceled(@SuppressWarnings("unused") MenuEvent e) {
		// unimplemented
	    }
	});
	
	return plg;
    }
    
    private JMenu createGenerateImageMenu()
    {
	final JMenuItem error, subdivision;
	JMenu generate = MenuBuilder.createMenuEntry("Visiona");
	
	subdivision = MenuBuilder.createMenuSubEntry("QuadTree",
		new ImageIcon(FileUtils.getResource("quad-tree.gif")),
		new ActionListener() {
                    @Override
		    public void actionPerformed(@SuppressWarnings("unused") ActionEvent e)
		    {
                	MyJLabel.this.parent.createQuadTreeSubdivisionImageWindow();
		    }
		});
	
	error = MenuBuilder.createMenuSubEntry("Errori",
		new ActionListener() {
                    @Override
		    public void actionPerformed(@SuppressWarnings("unused") ActionEvent e)
		    {
                	MyJLabel.this.parent.createQuadTreeErrorImageWindow();
		    }
		});
	
	generate.addMenuListener(new MenuListener() {
	    @Override
	    public void menuSelected(@SuppressWarnings("unused") MenuEvent e)
	    {
		if(MyJLabel.this.getQuadTree() == null) {
		    subdivision.setEnabled(false);
		    error.setEnabled(false);
		}
		
		else {		    
		    subdivision.setEnabled(true);
		    error.setEnabled(true);
		}
	    }
	    
	    @Override
	    public void menuDeselected(@SuppressWarnings("unused") MenuEvent e) {
		// unimplemented
	    }
	    
	    @Override
	    public void menuCanceled(@SuppressWarnings("unused") MenuEvent e) {
		// unimplemented
	    }
	});
	
	generate.add(subdivision);
	generate.add(error);
	return generate;
    }
    
    private JMenu createZoomMenu()
    {
	ButtonGroup radioGroup = new ButtonGroup();
	final JMenu zoom = MenuBuilder.createMenuEntry("Zoom");
	
	zoom.add(MenuBuilder.createMenuRadioEntry("Reimposta zoom",
		new ImageIcon(FileUtils.getResource("zoom_fit.png")),
		radioGroup,
		true,
		new ActionListener()
		{    
		    @Override
		    public void actionPerformed(@SuppressWarnings("unused") ActionEvent e)
		    {
			MyJLabel.this.scaleImageContent(-1);
			MainWindow.menuShortcutsBugWorkaround();
		    }
		}));
	
	zoom.add(MenuBuilder.createMenuRadioEntry("Zoom 25%",
		new ImageIcon(FileUtils.getResource("zoom_out.png")),
		radioGroup,
		false,
		new ActionListener()
		{    
		    @Override
		    public void actionPerformed(@SuppressWarnings("unused") ActionEvent e)
		    {
			MyJLabel.this.scaleImageContent(25);
			MainWindow.menuShortcutsBugWorkaround();
		    }
		}));
	
	zoom.add(MenuBuilder.createMenuRadioEntry("Zoom 50%",
		new ImageIcon(FileUtils.getResource("zoom_out.png")),
		radioGroup,
		false,
		new ActionListener()
		{    
		    @Override
		    public void actionPerformed(@SuppressWarnings("unused") ActionEvent e)
		    {
			MyJLabel.this.scaleImageContent(50);
			MainWindow.menuShortcutsBugWorkaround();
		    }
		}));
	
	zoom.add(MenuBuilder.createMenuRadioEntry("Zoom 75%",
		new ImageIcon(FileUtils.getResource("zoom_out.png")),
		radioGroup,
		false,
		new ActionListener()
		{    
		    @Override
		    public void actionPerformed(@SuppressWarnings("unused") ActionEvent e)
		    {
			MyJLabel.this.scaleImageContent(75);
			MainWindow.menuShortcutsBugWorkaround();
		    }
		}));
	
	zoom.add(MenuBuilder.createMenuRadioEntry("Zoom 100%",
		new ImageIcon(FileUtils.getResource("zoom.png")),
		radioGroup,
		false,
		new ActionListener()
		{    
		    @Override
		    public void actionPerformed(@SuppressWarnings("unused") ActionEvent e)
		    {
			MyJLabel.this.scaleImageContent(100);
			MainWindow.menuShortcutsBugWorkaround();
		    }
		}));
	
	zoom.add(MenuBuilder.createMenuRadioEntry("Zoom 150%",
		new ImageIcon(FileUtils.getResource("zoom_in.png")),
		radioGroup,
		false,
		new ActionListener()
		{    
		    @Override
		    public void actionPerformed(@SuppressWarnings("unused") ActionEvent e)
		    {
			MyJLabel.this.scaleImageContent(150);
			MainWindow.menuShortcutsBugWorkaround();
		    }
		}));
	
	zoom.add(MenuBuilder.createMenuRadioEntry("Zoom 200%",
		new ImageIcon(FileUtils.getResource("zoom_in.png")),
		radioGroup,
		false,
		new ActionListener()
		{    
		    @Override
		    public void actionPerformed(@SuppressWarnings("unused") ActionEvent e)
		    {
			MyJLabel.this.scaleImageContent(200);
			MainWindow.menuShortcutsBugWorkaround();
		    }
		}));
	
	zoom.addMenuListener(new MenuListener() {
	    @Override
	    public void menuSelected(@SuppressWarnings("unused") MenuEvent e)
	    {		
		for(int i = 0; i < zoom.getItemCount(); ++i)
		{
		    JMenuItem item = zoom.getItem(i);
		    
		    if(item.getText().startsWith("Reimposta ")) {
			continue;
		    }
		    
		    else if(item.getText().endsWith(" " + new Integer(MyJLabel.this.zoomFactor) + "%")) {
			item.setSelected(true);
			item.setEnabled(false);
		    }
		    
		    else {
			item.setSelected(false);
			item.setEnabled(true);
		    }
		}
	    }
	    
	    @Override
	    public void menuDeselected(@SuppressWarnings("unused") MenuEvent e) {
		// unimplemented
	    }
	    
	    @Override
	    public void menuCanceled(@SuppressWarnings("unused") MenuEvent e) {
		// unimplemented
	    }
	});
	
	return zoom;
    }
    
    public void prepareQuadTreeImage()
    {
	if(this.polygon.isClosed()) {
	    this.quadTree.prepareImage(this.externalColor, this.polygon, this.internalColor);
	}
	
	else {
	    this.quadTree.prepareImage(this.externalColor);
	}
    }

    /* (non-Javadoc)
     * @see javax.swing.JComponent#paintComponent(java.awt.Graphics)
     */
    @Override
    protected void paintComponent(Graphics g)
    {
	super.paintComponent(g);
	this.activeImage.paintComponent((Graphics2D)g, MyJLabel.this.zoomFactor);
	this.polygon.paintComponent((Graphics2D)g, MyJLabel.this.zoomFactor);
    }
}
